library(tidyverse)
library(readr)
chic <- read_csv("ggplot2/ggModify/chicago-nmmaps.csv")
chic <- chic %>%
  mutate(year = substr(date, 1, 4))

# 1. 给数据加标签
#   为了避免文本标签的重叠和拥挤，我们只用原始数据的1%，同样代表四个季节。
#   我们使用的是geom_label()，它有一个label的新aes（）:
sample <- chic %>%
  group_by(season) %>%
  sample_frac(0.01)

ggplot(sample, aes(x = date, y = temp, color = season)) +
  geom_point() +
  geom_label(aes(label = season), hjust = 0.5, vjust = -0.5) +
  labs(x = "Year", y = "Temperature (°F)") +
  xlim(as.Date(c("1997-01-01", "2000-12-31"))) +
  ylim(c(0, 90)) +
  theme(legend.position = "none")

# 如果你不喜欢标签周围的方框，也可以使用geom_text()：
ggplot(sample, aes(x = date, y = temp, color = season)) +
  geom_point() +
  geom_text(aes(label = season), hjust = 0.5, vjust = -0.5) +
  labs(x = "Year", y = "Temperature (°F)") +
  xlim(as.Date(c("1997-01-01", "2000-12-31"))) +
  ylim(c(0, 90)) +
  theme(legend.position = "none")

# ggrepel，它为ggplot2提供了geoms来防止文本重叠。
#   只需将geom_text()替换为geom_text_repel()，将geom_label()替换为geom_label_repel():
library(ggrepel)

ggplot(sample, aes(x = date, y = temp, color = season)) +
  geom_point() +
  geom_label_repel(aes(label = season), fontface = "bold") +
  labs(x = "Year", y = "Temperature (°F)") +
  theme(legend.position = "none")

# 白色填充框可能看起来更好，所以我们将season映射到fill而不是color，并设置一个白色的填充文本:
ggplot(sample, aes(x = date, y = temp)) +
  geom_point(data = chic, size = .5) +
  geom_point(aes(color = season), size = 1.5) +
  geom_label_repel(aes(label = season, fill = season),
                   color = "white", fontface = "bold",
                   segment.color = "grey30") +
  labs(x = "Year", y = "Temperature (°F)") +
  theme(legend.position = "none")

# 2. 添加文本注释
#   ggplot有几种添加文本注释的方法。我们将再次使用geom_text()或geom_label():
g <- ggplot(chic, aes(x = temp, y = dewpoint)) +
  geom_point(alpha = .5) +
  labs(x = "Temperature (°F)", y = "Dewpoint")

g + geom_text(aes(
  x = 25,
  y = 60,
  stat = "unique",
  label = "This is a useful annotation."
))

# 顺便说一下，当然可以改变显示文本的属性:
g +
  geom_text(aes(x = 25, y = 60,
                label = "This is a useful annotation"),
            stat = "unique", family = "Bangers",
            size = 7, color = "darkcyan")

# 3. facet
# 如果你打算用facet函数来可视化数据，可能会遇到麻烦。比如，你可能只希望注释一次:
ann <- data.frame(
  o3 = 30,
  temp = 20,
  season = factor("Summer", levels = levels(chic$season)),
  label = "Here is enough space\nfor some annotations."
)

g <-
  ggplot(chic, aes(x = o3, y = temp)) +
  geom_point() +
  labs(x = "Ozone", y = "Temperature (°F)")

g +
  geom_text(data = ann, aes(label = label),
            size = 7, fontface = "bold",
            family = "Roboto Condensed") +
  facet_wrap(~season)

# 另一个挑战是多个具有不同刻度的面板图，这可能会切割你的文本:
g +
  geom_text(aes(x = 23, y = 97,
                label = "This is not a useful annotation"),
            size = 5, fontface = "bold") +
  scale_y_continuous(limits = c(NA, 100)) +
  facet_wrap(~season, scales = "free_x")

# 一种解决方法是事先计算坐标轴的中点，这里是x轴的中点:

library(tidyverse)
(ann <-
  chic %>%
  group_by(season) %>%
  summarize(o3 = min(o3, na.rm = TRUE) +
              (max(o3, na.rm = TRUE) - min(o3, na.rm = TRUE)) / 2))

# 并使用聚合的数据来指定注释的位置:
g +
  geom_text(data = ann,
            aes(x = o3, y = 97,
                label = "This is a useful annotation"),
            size = 5, fontface = "bold") +
  scale_y_continuous(limits = c(NA, 100)) +
  facet_wrap(~season, scales = "free_x")

# 然而，有一种更简单的方法(就修复坐标而言)——但记住代码也需要一段时间。
# grid包结合ggplot2的annotation_custom()允许你根据缩放的坐标指定位置，
# 其中0为low，1为high。grobTree()创建网格图形对象，textGrob创建文本图形对象。
# 当你有多个不同刻度的图时，这种方法尤其有用。
library(grid)
my_grob <- grobTree(textGrob("This text stays in place!",
                             x = .1, y = .9, hjust = 0,
                             gp = gpar(col = "black",
                                       fontsize = 15,
                                       fontface = "bold")))

g +
  annotation_custom(my_grob) +
  facet_wrap(~season, scales = "free_x") +
  scale_y_continuous(limits = c(NA, 100))

# 4. 使用Markdown和HTML渲染标注
#   ggtext包，该包是为改进ggplot2的文本渲染而设计的。
#   ggtext包定义了两个新的主题元素，element_markdown()和element_textbox()。
#   该包还提供了额外的geoms。Geom_richtext()替代了geom_text()和geom_label()，
#   并将文本渲染为markdown…
library(ggtext)

lab_md <- "This plot shows **temperature** in *°F* versus **ozone level** in *ppm*"

g +
  geom_richtext(aes(x = 35, y = 3, label = lab_md),
                stat = "unique")

# 或html:
lab_html <- "&#9733; This plot shows <b style='color:red;'>temperature</b> in <i>°F</i> versus <b style='color:blue;'>ozone level</b>in <i>ppm</i> &#9733;"

g +
  geom_richtext(aes(x = 33, y = 3, label = lab_html),
                stat = "unique")

# geom提供了很多可以修改的细节，
#   比如angle(这在默认的geom_text()和geom_label()中是不支持的)、框的属性和文本的属性。
g +
  geom_richtext(aes(x = 10, y = 25, label = lab_md),
                stat = "unique", angle = 30,
                color = "white", fill = "steelblue",
                label.color = NA, hjust = 0, vjust = 0,
                family = "Playfair Display")

# ggtext包中的另一个geom是geom_textbox()。这个geom允许动态包装字符串，这对于较长的注释(如信息框和字幕)非常有用。
lab_long <- "**Lorem ipsum dolor**<br><i style='font-size:8pt;color:red;'>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.<br>Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</i>"

g +
  geom_textbox(aes(x = 40, y = 10, label = lab_long),
               width = unit(15, "lines"), stat = "unique")
